#include "stdafx.h"
#include "code/digeststream.hpp"


namespace JHCPP
{
	namespace code
	{
		///////////////////////////////////////////////////////////
		//CDigestBuf
		///////////////////////////////////////////////////////////
		const int CDigestBuf::BUFFER_SIZE = 256;

		CDigestBuf::CDigestBuf(CDigestEngine& eng)
		: BufferedStreamBuf(BUFFER_SIZE, std::ios::out), 
		m_eng(eng), 
		m_pIstr(0),
		m_pOstr(0) 
		{
		}

		CDigestBuf::CDigestBuf(CDigestEngine& eng, std::istream& istr)
		: BufferedStreamBuf(BUFFER_SIZE, std::ios::in), 
		m_eng(eng), 
		m_pIstr(&istr), 
		m_pOstr(0)
		{
		}

		CDigestBuf::CDigestBuf(CDigestEngine& eng, std::ostream& ostr)
		: BufferedStreamBuf(BUFFER_SIZE, std::ios::out), 
		m_eng(eng), 
		m_pIstr(0), 
		m_pOstr(&ostr)
		{
		}

		CDigestBuf::~CDigestBuf()
		{
		}

		int CDigestBuf::readFromDevice(char* buffer, std::streamsize length)
		{
			if (m_pIstr && m_pIstr->good())
			{
				m_pIstr->read(buffer, length);
				std::streamsize n = m_pIstr->gcount();
				if (n > 0) 
					m_eng.update(buffer, static_cast<unsigned>(n));
				return static_cast<int>(n);
			}
			return -1;
		}

		int CDigestBuf::writeToDevice(const char* buffer, std::streamsize length)
		{
			m_eng.update(buffer, (unsigned) length);
			if (m_pOstr) 
				m_pOstr->write(buffer, length);
			return static_cast<int>(length);
		}

		void CDigestBuf::close()
		{
			sync();
			if (m_pOstr) 
				m_pOstr->flush();
		}


		///////////////////////////////////////////////////////////
		//CDigestIOS
		///////////////////////////////////////////////////////////
		CDigestIOS::CDigestIOS(CDigestEngine& eng) : m_buf(eng)
		{
		}

		CDigestIOS::CDigestIOS(CDigestEngine& eng, std::istream& istr) : m_buf(eng, istr)
		{
		}

		CDigestIOS::CDigestIOS(CDigestEngine& eng, std::ostream& ostr) : m_buf(eng, ostr)
		{
		}

		CDigestIOS::~CDigestIOS()
		{
		}

		CDigestBuf* CDigestIOS::rdbuf()
		{
			return &m_buf;
		}

		///////////////////////////////////////////////////////////
		//CDigestInputStream
		///////////////////////////////////////////////////////////
		CDigestInputStream::CDigestInputStream(CDigestEngine& eng, std::istream& istr)
		: CDigestIOS(eng, istr), 
		std::istream(&m_buf)
		{
		}

		CDigestInputStream::~CDigestInputStream()
		{
		}


		///////////////////////////////////////////////////////////
		//CDigestOutputStream
		///////////////////////////////////////////////////////////
		CDigestOutputStream::CDigestOutputStream(CDigestEngine& eng)
		: CDigestIOS(eng), 
		std::ostream(&m_buf)
		{
		}

		CDigestOutputStream::CDigestOutputStream(CDigestEngine& eng, std::ostream& ostr)
		: CDigestIOS(eng, ostr), 
		std::ostream(&m_buf)
		{
		}


		CDigestOutputStream::~CDigestOutputStream()
		{
		}


		void CDigestOutputStream::close()
		{
			m_buf.close();
		}

	}//end of namespace code
}//end of namespace JHCPP
